package com.freeman.cement.config;

import com.freeman.cement.annotation.NeedRole;
import com.freeman.cement.exception.AppException;
import com.freeman.cement.exception.AppExceptionCodeMsg;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import org.aspectj.lang.reflect.MethodSignature;
import java.util.Set;


@Component
@Aspect
public class AopConfig {

    //定义一个切点（通过注解）
    @Pointcut("@annotation(com.freeman.cement.annotation.NeedRole))")
    public void pointcut(){}


    //前置通知
    @Before("pointcut()")
    public void before(JoinPoint joinPoint){
        System.out.println("verify user role-------------");

        //获取到HttpServletRequest，ThreadLocal
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        //获取验证token时存入的角色/权限
        Object userRole = request.getAttribute("userRole");
        //获取当前请求的方法上的注解hasRole中设置的角色
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        //反射获取当前被调用的方法
        Method method = signature.getMethod();

        //判断当前方法是否有hasRole注解
        //如果有，判断是否用户具有注解属性中要求的角色
        //如果没有hasRole注解，那么说明方法不需要判断用户的角色，可以匿名访问
        NeedRole needRole = method.getDeclaredAnnotation(NeedRole.class);
        if(needRole != null && (userRole == null || !needRole.value().contains(userRole.toString()))){
            System.out.println("no access-------------");
            throw new AppException(AppExceptionCodeMsg.NO_AUTHORITY);
        }
        System.out.println("allow access-------------");
    }
}